import bpy
from bpy.types import Operator, Object
from bpy.props import StringProperty
from ...libs.functions.get_common_vars import get_common_vars
from ...libs.functions.animation import anim_attrs
from ...libs.functions.basics import ocultar_post_panel_settings


class FLUIDLAB_OT_colliders_animation_buttons(Operator):
    bl_idname = "fluidlab.colliders_animation_buttons"
    bl_label = "Button"
    bl_description = "Animation Button"
    bl_options = {"REGISTER", "UNDO"}

    call_from: StringProperty(default="")


    def reset_control_props(self, props, type_button, call_from) -> None:

        # Seteamos los estados de los booleans de control:
        if type_button.lower() == "add":
            setattr(props, call_from + "_animed", True)

        if type_button.lower() == "remove":
            setattr(props, call_from + "_animed", False)

        ocultar_post_panel_settings()


    def update_button(self, type_props, call_from) -> None:
        # ejecutamos este mismo operador pero primero hacemos un remove y luego un add:
        bpy.ops.fluidlab.colliders_animation_buttons(call_from="Remove" +"."+ type_props +"."+ call_from)
        bpy.ops.fluidlab.colliders_animation_buttons(call_from="Add" +"."+ type_props +"."+ call_from)


    def exception_enable_disable(self, collider_ob:Object, props, type_button, type_props, call_from) -> None:

        #------------------------------------#
        #      Exception enable_disable      #
        #------------------------------------#

        condition = props.enable_disable_from_to == 'ON_OFF'
        _from = True if condition else False
        _to = False if condition else True
        _start = getattr(props, call_from + "_start")

        if type_button.upper() == 'ADD':
            add_dpath = "use"
            
            data =  {
                            'object':  collider_ob.collision, 
                            'dpath':   add_dpath, 
                            'frame':   _start,
                            'value':   _from
            }
            anim_attrs(data)

            data =  {
                        'object':  collider_ob.collision, 
                        'dpath':   add_dpath, 
                        'frame':   getattr(props, call_from + "_start")+1,
                        'value':   _to
            }
            anim_attrs(data)

        elif type_button.upper() == 'REMOVE':
            rm_dpath = "collision.use"

            if not collider_ob.animation_data:
                self.report({'ERROR'}, f"{collider_ob.name} not have animation_data!")
                return {'CANCELLED'}

            
            action = collider_ob.animation_data.action
            if not action:
                self.report({'ERROR'}, f"{collider_ob.name} not have action!")
                return {'CANCELLED'}


            if not collider_ob.animation_data.action.fcurves:
                self.report({'ERROR'}, f"{collider_ob.name} not have fcurves!")
                return {'CANCELLED'}


            fcurve = action.fcurves.find(data_path=rm_dpath, index=0)
            if not fcurve:
                self.report({'ERROR'}, f"{collider_ob.name} not have fcurve {rm_dpath}!")
                return {'CANCELLED'}
            
            action.fcurves.remove(fcurve)

        
        elif type_button.upper() == 'UPDATE':
            self.update_button(type_props, call_from)
                
        self.reset_control_props(props, type_button, call_from)
        return {'FINISHED'}

    
    def execute(self, context):

        fluid_colliders = get_common_vars(context, get_fluid_colliders=True)
        active_collider_item = fluid_colliders.active
        
        if not active_collider_item:
            self.report({'ERROR'}, "Not valid active_collider_item!")
            return {'CANCELLED'}
        
        # Ahora los colliders pueden ser varios:
        colliders_obs = [c_ob.ob for c_ob in active_collider_item.colliders]
        if not colliders_obs:
            self.report({'ERROR'}, "Not valid collider object!")
            return {'CANCELLED'}
        
        for collider_ob in colliders_obs:

            ob_with_anim = collider_ob.collision
            
            type_button, type_props, call_from = self.call_from.split(".")
            # print(type_button, type_props, call_from) # -> por ejemplo: Add colliders permeability

            props = getattr(active_collider_item, type_props) # List Colliders Props

            # para la escepción de animar el use_viscoelastic_springs:
            if call_from == "enable_disable":
                return self.exception_enable_disable(collider_ob, props, type_button, type_props, call_from)

            _start = getattr(props, call_from + "_start")
            _from = getattr(props, call_from + "_from")
            _increase = getattr(props, call_from + "_increase")
            _duration = getattr(props, call_from + "_duration")
            _decrease = getattr(props, call_from + "_decrease")
            _to = getattr(props, call_from + "_to")
            _increase_decrease = getattr(props, call_from + "_inc_dec")
            
            if type_button.upper() == 'ADD':

            # el dpath de los insertkeyframe es objeto.collsion y su dpath "property"
                add_dpath = call_from
                
                data =  {
                                'object':  ob_with_anim, 
                                'dpath':   add_dpath, 
                                'frame':   _start,
                                'value':   _from
                }
                anim_attrs(data)

                if _increase_decrease:
                    data =  {
                                'object':  ob_with_anim, 
                                'dpath':   add_dpath, 
                                'frame':   _start + _increase,
                                'value':   _to
                    }
                    anim_attrs(data)

                frame = getattr(props, call_from + "_start") + getattr(props, call_from + "_duration")
                data =  {
                            'object':  ob_with_anim, 
                            'dpath':   add_dpath, 
                            'frame':   frame,
                            'value':   _to
                }
                anim_attrs(data)

                if _increase_decrease:
                    data =  {
                                'object':  ob_with_anim, 
                                'dpath':   add_dpath, 
                                'frame':   _start + _duration + _decrease,
                                'value':   _from
                    }
                    anim_attrs(data)

            elif type_button.upper() == 'REMOVE':

                # pero en el remove si necesita el objeto y su dpath "collision.property"
                rm_dpath = "collision." + call_from

                if not collider_ob.animation_data:
                    self.report({'ERROR'}, f"{collider_ob.name} not have animation_data!")
                    return {'CANCELLED'}

                
                action = collider_ob.animation_data.action
                if not action:
                    self.report({'ERROR'}, f"{collider_ob.name} not have action!")
                    return {'CANCELLED'}


                if not collider_ob.animation_data.action.fcurves:
                    self.report({'ERROR'}, f"{collider_ob.name} not have fcurves!")
                    return {'CANCELLED'}


                fcurve = action.fcurves.find(data_path=rm_dpath, index=0)
                if not fcurve:
                    self.report({'ERROR'}, f"{collider_ob.name} not have fcurve {rm_dpath}!")
                    return {'CANCELLED'}
                
                action.fcurves.remove(fcurve)

            elif type_button.upper() == 'UPDATE':
                self.update_button(type_props, call_from)
            
            self.reset_control_props(props, type_button, call_from)
        
        return {'FINISHED'}